Layout Qualifiers

Input Layout Qualifiers

  • location = N

    • Assigns an input/output location index for vertex inputs, fragment outputs, or varyings. Used for linking stages and for vertex attribute bindings. (maps to SPIR-V Location ). docs.vulkan.org

  • binding = B  and set = S

    • Assign descriptor binding number and descriptor set index for opaque/descriptor resources (uniform buffers, storage buffers, samplers, images).

  • offset = N  and align = A

    • explicitly control byte offsets and alignment of members inside interface/UBO/SSBO blocks; they map to the SPIR-V Offset / ArrayStride / MatrixStride  decorations for struct members.

    • Use when you need explicit control over memory layout.

  • push_constant

    • (block qualifier)

    • Marks a uniform block as push constants.

    • They must be declared in the pipeline layout as push-constant ranges.

  • constant_id = N  (specialization constants)

    • Make a const  scalar into a SPIR-V specialization constant whose value can be supplied at pipeline creation time (allows driver optimization without full shader recompile).

  • Interpolation and qualifiers: flat , noperspective , centroid , sample , invariant

    • control interpolation rules or invariance; they map to SPIR-V interpolation/built-in decorations or decorations affecting interpolation

  • Location and Component Interface .

Location
layout(location = 3) in vec4 normal;
const int start = 6;
layout(location = start + 2) in vec4 v;
  • In this example the shader input normal  is assigned to vector location number 3 and v  is assigned location number 8. For vertex shader inputs, the location specifies the number of the vertex attribute from which input values are taken. For inputs of all other shader types, the location specifies a vector number that can be used to match against outputs from a previous shader stage, even if that shader is in a different program object.

  • The following language describes how many locations are consumed by a given type. However, geometry shader inputs, tessellation control shader inputs and outputs, and tessellation evaluation inputs all have an additional level of arrayness relative to other shader inputs and outputs. This outer array level is removed from the type before considering how many locations the type consumes.

  • If the declared input (after potentially removing an outer array level as just described above) is an array of size n  and each of the elements takes m  locations, it will be assigned m  * n  consecutive locations starting with the location specified. For example,

layout(location = 6) in vec4 colors[3];
  • will establish that the shader input colors  is assigned to vector location numbers 6, 7, and 8.

  • If the declared input is an n  Γ— m  matrix, it will be assigned multiple locations starting with the location specified. The number of locations assigned for each matrix will be the same as for an n -element array of m -component vectors. For example,

layout(location = 9) in mat4 transforms[2];
  • will establish that shader input transforms  is assigned to vector locations 9-16, with transforms[0]  being assigned to locations 9-12, and transforms[1]  being assigned to locations 13-16.

  • If the declared input is a structure or block, its members will be assigned consecutive locations in their order of declaration, with the first member assigned the location provided in the layout qualifier. For a structure, this process applies to the entire structure. It is a compile-time error to use a location  qualifier on a member of a structure. For a block, this process applies to the entire block, or until the first member is reached that has a location  layout qualifier.

  • When a block member is declared with a location  qualifier, its location comes from that qualifier; the member’s location  qualifier overrides the block-level declaration. Subsequent members are again assigned consecutive locations, based on the newest location, until the next member declared with a location  qualifier. The values used for locations do not have to be declared in increasing order.

  • If a block has no block-level location  layout qualifier, it is required that either all or none of its members have a location  layout qualifier, or a compile-time error results. For some blocks declared as arrays, the location  can only be applied at the block level: When a block is declared as an array where additional locations are needed for each member for each block array element, it is a compile-time error to specify locations on the block members. For arrayed  interfaces (those generally having an extra level of arrayness due to interface expansion), the outer array is stripped before applying this rule.

  • When generating SPIR-V, all in  and out  qualified user-declared (non built-in) variables and blocks (or all their members) must have a shader-specified location . Otherwise, a compile-time error is generated.

  • The locations consumed by block and structure members are determined by applying the rules above recursively as though the structure member were declared as an input variable of the same type. For example:

layout(location = 3) in struct S
{
    vec3 a;                      // gets location 3
    mat2 b;                      // gets locations 4 and 5
    vec4 c[2];                   // gets locations 6 and 7
    layout(location = 8) vec2 A; // ERROR, can't use on struct member
} s;
layout(location = 4) in block
{
    vec4 d;                      // gets location 4
    vec4 e;                      // gets location 5
    layout(location = 7) vec4 f; // gets location 7
    vec4 g;                      // gets location 8
    layout(location = 1) vec4 h; // gets location 1
    vec4 i;                      // gets location 2
    vec4 j;                      // gets location 3
    vec4 k;                      // ERROR, location 4 already used
};
  • The number of input locations available to a shader is limited. For vertex shaders, the limit is the advertised number of vertex attributes. For all other shaders, the limit is implementation-dependent and must be no less than one fourth of the advertised maximum input component count.

  • program will fail to link if any attached shader uses a location greater than or equal to the number of supported locations, unless device-dependent optimizations are able to make the program fit within available hardware resources.
    A program will fail to link if explicit location assignments leave the linker unable to find space for other variables without explicit assignments.
    For the purposes of determining if a non-vertex input matches an output from a previous shader stage, the location  layout qualifier (if any) must match.

Component
  • The component  qualifier allows the location to be more finely specified for scalars and vectors, down to the individual components within a location that are consumed. It is a compile-time error to use component  without also specifying the location  qualifier (order does not matter). The components within a location are 0, 1, 2, and 3. A variable or block member starting at component N  will consume components N , N+1 , N+2 , …​ up through its size. It is a compile-time error if this sequence of components gets larger than 3. A scalar double  will consume two of these components, and a dvec2  will consume all four components available within a location. A dvec3  or dvec4  can only be declared without specifying a component . A dvec3  will consume all four components of the first location and components 0 and 1 of the second location. This leaves components 2 and 3 available for other component-qualified declarations.

// a consumes components 2 and 3 of location 4
layout(location = 4, component = 2) in vec2 a;

// b consumes component 1 of location 4
layout(location = 4, component = 1) in float b;

// ERROR: c overflows component 3
layout(location = 3, component = 2) in vec3 c;

// d consumes components 2 and 3 of location 5
layout(location = 5, component = 2) in double d;

// ERROR: e overflows component 3 of location 6
layout(location = 6, component = 2) in dvec2 e;

// ERROR: f overlaps with g
layout(location = 7, component = 0) in vec2 f;
layout(location = 7, component = 1) in float g;

layout(location = 8) in dvec3 h; // components 0,1,2 and 3 of location 8
                                 // and components 0 and 1 of location 9
layout(location = 9, component = 2) in double i; // okay, compts 2 and 3
  • If the variable is an array, each element of the array, in order, is assigned to consecutive locations, but all at the same specified component within each location. For example:

// component 3 is consumed in each of 6 locations
layout(location = 2, component = 3) in float d[6];
  • That is, location 2 component 3 will hold d[0] , location 3 component 3 will hold d[1] , …​, up through location 7 component 3 holding d[5] .

  • This allows packing of two arrays into the same set of locations:

// e consumes beginning (components 0, 1 and 2) of each of 6 slots
layout(location = 0, component = 0) in vec3 e[6];

// f consumes last component of the same 6 slots
layout(location = 0, component = 3) in float f[6];
  • If applying this to an array of arrays, all levels of arrayness are removed to get to the elements that are assigned per location to the specified component. These non-arrayed elements will fill the locations in the order specified for arrays of arrays in β€œ Arrays ”.

  • It is a compile-time error to apply the component  qualifier to a matrix, a structure, a block, or an array containing any of these. It is a compile-time error to use component  1 or 3 as the beginning of a double  or dvec2 . It is a link-time error to specify different components for the same variable within a program.

Location Aliasing
  • Location aliasing  is causing two variables or block members to have the same location number. Component aliasing  is assigning the same (or overlapping) component numbers for two location aliases. (Recall if component  is not used, components are assigned starting with 0.) With one exception, location aliasing is allowed only if it does not cause component aliasing; it is a compile-time or link-time error to cause component aliasing. Further, when location aliasing, the aliases sharing the location must have the same underlying numerical type and bit width (floating-point or integer, 32-bit versus 64-bit, etc.) and the same auxiliary storage and interpolation qualification. The one exception where component aliasing is permitted is when targeting OpenGL for two input variables (not block members) to a vertex shader, which are allowed to have component aliasing. This vertex-variable component aliasing is intended only to support vertex shaders where each execution path accesses at most one input per aliased component. Implementations are permitted, but not required, to generate link-time errors if they detect that every path through the vertex shader executable accesses multiple inputs aliased to any single component.